﻿using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using System.Xml;
using Core;


namespace GraphControls
{
    public partial class GraphControl : UserControl
    {
        public Graph Structure { get; set; }
        public byte CurrentItem { get; set; }
        private int _currentX;
        private int _currentY;
        private bool _isfirstNode = true;
        private Node _linkedNode;
        private bool draganddroped = false;
        private bool dragelinks = false;
        private Node startNode = null;
        private Graphics g = null;
        private bool isSelectNode = false;
        private bool isSelectLink = false;
        private bool _multSelectdraw = false;
        private bool _multSelectdrawEnd = false;
        private bool _multSelect = false;
        private int _mx;
        private int _my;
        private int _cmx;
        private int _cmy;
        private int xx = 0;
        private int yy = 0;
        private bool IsFerst = true;
        public event EventHandler SelectNodeEvent;
        public event EventHandler SelectLinkEvent;
        private ProjectsControl _projectsControl;

        public GraphControl(ProjectsControl projectsControl)
        {
            _projectsControl = projectsControl;
            this.SetStyle(ControlStyles.DoubleBuffer| ControlStyles.AllPaintingInWmPaint | ControlStyles.SupportsTransparentBackColor | ControlStyles.UserPaint, true);
            this.UpdateStyles();
            InitializeComponent();
            g = this.CreateGraphics();
            Structure = new Graph();
        }

        private void GraphControl_MouseClick(object sender, MouseEventArgs e)
        {
            _currentX = e.X;
            _currentY = e.Y;
           if(e.Button == MouseButtons.Left)
           {
               switch (CurrentItem)
               {
                   case 4:
                       {
                           Structure.AddNode(e.X, e.Y, "", 2);
                           Structure.SelectedNode.DrawNode(g);
                           break;
                       }
                   
                   case 2:
                       {
                           Structure.AddNode(e.X, e.Y, "",1);
                           Structure.SelectedNode.DrawNode(g);
                           break;
                       }
                   case 1:
                       {
                           Structure.AddNode(e.X, e.Y, "",0);
                           Structure.SelectedNode.DrawNode(g);
                           break;
                       }
                   case 3:
                       {
                           if(_isfirstNode)
                           {
                               _linkedNode = Structure.SelectNode(e.X, e.Y);
                               if (_linkedNode != null)
                                   _isfirstNode = false;
                           }
                           else
                           {

                               if((Structure.SelectNode(e.X,e.Y) != null) && (Structure.SelectedNode != _linkedNode))
                               {
                                   _linkedNode.SetLink(Structure.SelectedNode,"");
                                   _isfirstNode = true;
                                   Pen pen = new Pen(Color.Blue);
                                   g.DrawLine(pen, _linkedNode.X, _linkedNode.Y, Structure.SelectedNode.X, Structure.SelectedNode.Y);
                               }
                               if(Structure.SelectedNode != null)
                                   Structure.SelectedNode.UnSelect();
                               else
                               {
                                   _linkedNode = null;
                                   _isfirstNode = true;
                               }
                               
                                   
                           }
                               
                           break;
                       }
               }
               
           }
           else
           {
               if (Structure.SelectNode(_currentX,_currentY) != null)
               {
                   contextMenuStrip1.Show(this, e.X, e.Y);
                   isSelectNode = true;
                   contextMenuStrip1.Items[1].Enabled = false;
                   contextMenuStrip1.Items[2].Enabled = true;
                   contextMenuStrip1.Items[3].Enabled = true;
                   contextMenuStrip1.Items[4].Enabled = true;
                   начальнаяТочкаToolStripMenuItem.Enabled = true;
                   if(Structure.IsStartNode)
                   {
                       начальнаяТочкаToolStripMenuItem.Enabled = false;
                   }
               }
               if(Structure.SelectLink(e.X,e.Y))
               {
                   contextMenuStrip1.Show(this, e.X, e.Y);
                   contextMenuStrip1.Items[1].Enabled = true;
                   contextMenuStrip1.Items[2].Enabled = false;
                   contextMenuStrip1.Items[3].Enabled = false;
                   contextMenuStrip1.Items[4].Enabled = false;
                   isSelectLink = true;
               }

           }
           this.Invalidate();
        }

        private void УдалитьToolStripMenuItemClick(object sender, EventArgs e)
        {
            if(isSelectNode)
                Structure.DeleteNode();
            if(isSelectLink)
                Structure.DeleteLink();
            g.Clear(Color.White);
            this.Invalidate();
        }

        private void GraphControl_MouseDown(object sender, MouseEventArgs e)
        {
            if(CurrentItem == 0)
            {
                if (Structure.SelectNode(e.X, e.Y) != null)
                {
                    if (_multSelectdrawEnd)
                    {
                        _multSelect = true;
                        _mx = e.X;
                        _my = e.Y;
                    }
                    //SelectNodeEvent(this, null);
                    Structure.SelectedLink = null;
                    draganddroped = true;
                }
                else
                {
                    foreach (Node node in Structure.Struct)
                    {
                        node.IsSelected = false;
                    }
                }
                if (Structure.SelectLink(e.X, e.Y))
                {
                    Structure.SelectedNode = null;
                    //SelectLinkEvent(this, null); 
                    dragelinks = true;
                }
                if (!_multSelectdraw && !(draganddroped || dragelinks))
                {
                    _multSelectdraw = true;
                    _mx = e.X;
                    _my = e.Y;
                }
                
            }
        }

        private void GraphControl_MouseMove(object sender, MouseEventArgs e)
        {
            
            if (draganddroped)
            {
                Structure.SelectedNode.X = e.X;
                Structure.SelectedNode.Y = e.Y;
                this.Invalidate();
            }
            if (dragelinks)
            {
                Structure.SelectedLink.X = e.X;
                Structure.SelectedLink.Y = e.Y;
                this.Invalidate();
            }
            if(_multSelectdraw)
            {
                _cmx = e.X;
                _cmy = e.Y;
                foreach (var node in Structure.Struct)
                {
                    if ((node.X >= _mx) && (node.X <= _cmx) && (node.Y >= _my) && (node.Y <= _cmy))
                    {
                        node.IsSelected = true;
                    }
                }
                this.Invalidate();
            }
            if (_multSelect)
            {
                foreach (var node in Structure.Struct)
                {
                    if (node.IsSelected)
                    {
                        if (IsFerst)
                        {
                            node.SavePos();
                        }
                        if ((e.X > node.X - 10) && (e.X < node.X + 10)
                            && (e.Y > node.Y - 10) && (e.Y < node.Y + 10))
                        {
                            if (IsFerst)
                            {
                                xx = node.X;
                                yy = node.Y;
                            }
                            node.X = e.X;
                            node.Y = e.Y;
                            
                        }
                        else
                        {

                            node.X = e.X-xx + node.Xold;
                            node.Y = e.Y-yy + node.Yold;
                        }                        
                    }
                    
                }
                IsFerst = false;
            }
        }

        private void GraphControl_MouseUp(object sender, MouseEventArgs e)
        {
            draganddroped = false;
            dragelinks = false;
            if (_multSelectdrawEnd)
                _multSelect = false;
            if(_multSelectdraw)
                _multSelectdrawEnd = true;
            _multSelectdraw = false;
            IsFerst = true;
        }

        private void GraphControl_SizeChanged(object sender, EventArgs e)
        {
           // g = this.CreateGraphics();
        }

        private void GraphControl_Paint(object sender, PaintEventArgs e)
        {
           
            e.Graphics.Clear(Color.White);
            foreach (Node node in Structure.Struct)
            {
                foreach (Link link in node.Linking)
                {
                    link.DrawLink(e.Graphics, node);
                }
                node.DrawNode(e.Graphics);
            }

            if(_multSelectdraw)
            {
                Pen pen = new Pen(Color.Black);
                float[] ptrn = new float[] { 4.0F, 4.0F, 4.0F, 4.0F };
                pen.DashPattern = ptrn;
                Point[] points = new Point[5];
                points[0].X = _mx;
                points[0].Y = _my;
                points[1].X = _cmx;
                points[1].Y = _my;
                points[2].X = _cmx;
                points[2].Y = _cmy;
                points[3].X = _mx;
                points[3].Y = _cmy;
                points[4].X = _mx;
                points[4].Y = _my;
                e.Graphics.DrawPolygon(pen,points);
            }
        }

        private void обычнаяДугаToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Structure.SelectedLink.TOfLink=TypeOfLink.Message;
            this.Invalidate();
        }

        private void начальнаяТочкаToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Structure.SelectedNode.Nodetype = TypeOfNode.Client;
            Structure.IsStartNode = true;
            this.Invalidate();
        }

        public void SaveToXML(String filename)
        {
            //<process name="New" entry="L1" export="False" width="659" height="481" comment="">

            String result = "<process name=";
            int pos = filename.LastIndexOf(@"\");
            result += '"';
            result += filename.Substring(pos+1, filename.Length - pos - 5)+'"';
            result += " entry=" + '"' + Structure.StartNode.Id + '"' + " export=";
            result += '"' + "False" + '"' + " width=" +'"'+this.Width.ToString()+'"' +" height="
                +'"'+this.Height.ToString()+'"'+ " comment="+'"'+'"'+'>'+ "<nodes>";
            result += Structure.StartNode.ToString();
            foreach (Link link in Structure.StartNode.Linking)
            {
                result += link.ToString();
            }
            result += "</node>";
            foreach (Node node in Structure.Struct)
            {
                if(node != Structure.StartNode)
                {
                    result += node.ToString();
                    foreach (Link link in node.Linking)
                    {
                        result += link.ToString();
                    }
                    result += "</node>";
                }

            }
            result += "</nodes>"+"<comments />";
            result += "</process>";
            StreamWriter streamWriter = File.CreateText(filename);
            streamWriter.WriteLine(result);
            streamWriter.Flush();
        }

        public Graph OpenXML(String filename)
        {
            string prm = "";
            Graph result = new Graph();
            XmlTextReader reader = new XmlTextReader(filename);
            while (reader.Read())
            {
                switch (reader.NodeType)
                {
                    case XmlNodeType.Element: // Узел является элементом.
                        prm = prm + ("<" + reader.Name);
                        reader.ReadAttributeValue();
                        
                        string str = reader.Value;
                        while (reader.MoveToNextAttribute()) // Чтение атрибутов.
                            prm = prm + (" " + reader.Name + "='" + reader.Value + "'");
                        prm = prm + (">");
                        break;
                   
                }

            }
            return result;
        }

        public void NewDoc()
        {
            Structure =  new Graph();
            this.Invalidate();
        }

        private void Inv(object sender, EventArgs eventArgs)
        {
            this.Invalidate();
        }

        private void TestToolStripMenuItem_Click(object sender, EventArgs e)
        {
            PropertyView propertyView = new PropertyView();
            propertyView.Closed += Inv;
            if(Structure.IsNodeSelected)
                propertyView.Initialize(Structure.SelectedNode,this);
            else
            {
                propertyView.Initialize(Structure.SelectedLink, this);
            }
            propertyView.Show();
        }

        private void ServerPortToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Structure.SelectedNode.Nodetype = TypeOfNode.Server;
            Structure.IsStartNode = true;
            this.Invalidate();
        }

        private void завершающаяВершинаToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Structure.SelectedNode.Nodetype = TypeOfNode.Method;
            Structure.IsStartNode = true;
            this.Invalidate();
        }

        private void создатьПаруПортовToolStripMenuItem_Click(object sender, EventArgs e)
        {
            PortProperty portProperty = new PortProperty(_projectsControl,Structure.SelectedNode,this.Width,this.Height);
            portProperty.Show();
        }

        private void testToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            if(Structure.IsNodeSelected)
                System.Windows.Forms.MessageBox.Show(this, Structure.SelectedNode.ToString(),
                                                                    "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
            else
            {
                System.Windows.Forms.MessageBox.Show(this, Structure.SelectedLink.ToString(),
                                                                     "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); 
            }
            
        }

        private void сделатьСтартовойВершинойToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if ((Structure.SelectedNode != null) && (!Structure.IsStartNode))
            {
                Structure.SelectedNode.MakeStart(Structure);
            }
            else
            {
                System.Windows.Forms.MessageBox.Show(this, "В графе уже есть стартовая вершина",
                                                                     "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); 
            }
        }

        private void тождественноИстеннаяДугаToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Structure.SelectedLink.TOfLink = TypeOfLink.Condition;
            this.Invalidate();
        }

       
    }
}
